// 光照计算
Shader "Study/Chapter5/DefaultLight-shadow"
{
    Properties
    {
		_DiffuseIntensity("DiffuseIntensity ",float) = 1
        // 高光颜色
        _SpecularColor("SpecularColor",Color) = (1,1,1,1)
        // 高光系数
        _SpecularIntensity("SpecularIntensity",Range(0,10)) = 1
        // 高光范围
        _Shininess("Shininess",float) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
			#include "Lighting.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
				float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
				float3 worldPos : TEXCOORD0;
				float3 worldNormal : TEXCOORD1;
            };

			float4 _SpecularColor;
			float _SpecularIntensity;
			float _Shininess;
			float _DiffuseIntensity;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
				o.worldPos = mul(unity_ObjectToWorld,v.vertex);
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
				//Diffuse = Ambient + Kd * LightColor * dot(N,L) 
				fixed4 ambient = unity_AmbientSky;  // 当前定义的环境光（天空盒的颜色看起来是）
				fixed kd = _DiffuseIntensity;  		// 漫反射系数
				fixed4 lightColor = _LightColor0; 	// _LightColor0 默认定义的光照颜色
				float3 N = normalize(i.worldNormal);   // 法线归一化
				float3 L = normalize(_WorldSpaceLightPos0.xyz);			// 入射光线
				float NdotL = dot(N,L);									// 核心 范围从 -1~1
				// 但是，通常情况下 从暗面到亮面需要调整 为 0~1 ，即 将 -1~1 映射到 0~1
				// 这种称为 半 lamber 
				NdotL = NdotL * 0.5 + 0.5;
				fixed4 diffuse = ambient + kd * lightColor * NdotL;
				float3 V = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);   // 观察向量
				// 半角向量 H 即相当于入射光线和观察方向的中间向量
                float3 H = normalize(L+V);
				float NdotH = dot(N,H);
				fixed4 specular = _SpecularColor * _SpecularIntensity * pow(max(0,NdotH),_Shininess);

				fixed4 finalColor = diffuse + specular;
                return finalColor;
            }
            ENDCG
        }

        Pass
        {
            // 生成阴影
            //  添加"LightMode" = "ShadowCaster"的Pass.
            // 1.appdata中声明float4 vertex:POSITION;和half3 normal:NORMAL;这是生成阴影所需要的语义.
            // 2.v2f中添加V2F_SHADOW_CASTER;用于声明需要传送到片断的数据.
            // 3.在顶点着色器中添加TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)，主要是计算阴影的偏移以解决不正确的Shadow Acne和Peter Panning现象.
            // 4.在片断着色器中添加SHADOW_CASTER_FRAGMENT(i)
            Tags {"LightMode" = "ShadowCaster"}
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            // 定义在LightMode=ShadowCaster的Pass中，会自动生成两个宏:
            // 1. SHADOWS_DEPTH :用于生成直线光和聚光灯阴影.
            // 2. SHADOW_CUBE :用于生成点光源阴影.
            #pragma multi_compile_shadowcaster
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex :POSITION;
                half3 normal : NORMAL;
            };


            struct v2f
            {
                // 用于声明需要传送到片断的数据.
                V2F_SHADOW_CASTER;
            };


            v2f vert(appdata v)
            {
                v2f o;
                //主要是计算阴影的偏移以解决不正确的Shadow Acne和Peter Panning现象
                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)

                return o;
            }

            fixed4 frag(v2f i):SV_TARGET
            {
                // 内置的定义宏，没有查看到具体的逻辑
                SHADOW_CASTER_FRAGMENT(i)
            }
            ENDCG
        }
    }

     // 生成阴影
    //FallBack "Diffuse"
}
    
